package org.openmrs.module.hospitalcore.db.hibernate;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.openmrs.Concept;
import org.openmrs.Obs;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.DAOException;
import org.openmrs.module.hospitalcore.HospitalCoreService;
import org.openmrs.module.hospitalcore.concept.ConceptModel;
import org.openmrs.module.hospitalcore.concept.Mapping;
import org.openmrs.module.hospitalcore.db.HospitalCoreDAO;

public class HibernateHospitalCoreDAO implements HospitalCoreDAO {
	SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
	SimpleDateFormat formatterExt = new SimpleDateFormat("dd/MM/yyyy");
	private SessionFactory sessionFactory;
	
	
	
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}



	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}



	public List<Obs> listObsGroup(Integer personId, Integer conceptId, Integer min, Integer max) throws DAOException{
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Obs.class, "obs")
		.add(Restrictions.eq("obs.person.personId", personId))
		.add(Restrictions.eq("obs.concept.conceptId", conceptId))
		.add(Restrictions.isNull("obs.obsGroup"))
		.addOrder(Order.desc("obs.dateCreated"));
		if(max > 0){
			criteria.setFirstResult(min).setMaxResults(max);
		}
		List<Obs> list = criteria.list();
		return list;
	}
	
	public Obs getObsGroupCurrentDate(Integer personId, Integer conceptId) throws DAOException{
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Obs.class, "obs")
		.add(Restrictions.eq("obs.person.personId", personId))
		.add(Restrictions.eq("obs.concept.conceptId", conceptId))
		.add(Restrictions.isNull("obs.obsGroup"));
		String date = formatterExt.format(new Date());
		String startFromDate = date + " 00:00:00";
		String endFromDate = date + " 23:59:59";
		try {
			criteria.add(Restrictions.and(Restrictions.ge(
					"obs.dateCreated", formatter.parse(startFromDate)), Restrictions.le(
					"obs.dateCreated", formatter.parse(endFromDate))));
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("Error convert date: "+ e.toString());
			e.printStackTrace();
		}
		
		List<Obs> list = criteria.list();
		return CollectionUtils.isNotEmpty(list)? list.get(0) : null;
	}
	
	public Integer buildConcepts(List<ConceptModel> conceptModels) {

		HospitalCoreService hcs = Context.getService(HospitalCoreService.class);
		Session session = sessionFactory.getCurrentSession();
		Integer diagnosisNo = 0;
//		Transaction tx = session.beginTransaction();
//		tx.begin();
		for (int i = 0; i < conceptModels.size(); i++) {
			ConceptModel conceptModel = conceptModels.get(i);
			Concept concept = hcs.insertConcept(
					conceptModel.getConceptDatatype(),
					conceptModel.getConceptClass(), conceptModel.getName(), "",
					conceptModel.getDescription());
			System.out.println("concept ==> " + concept.getId());
			for (String synonym : conceptModel.getSynonyms()) {
				hcs.insertSynonym(concept, synonym);
			}

			for (Mapping mapping : conceptModel.getMappings()) {
				hcs.insertMapping(concept, mapping.getSource(),
						mapping.getSourceCode());
			}

			if (i % 20 == 0) {				
				session.flush();
				session.clear();
				System.out.println("Imported " + (i+1) + " diagnosis (" + (i/conceptModels.size()*100) + "%)");
			}
			diagnosisNo++;
		}
		return diagnosisNo;
//		tx.commit();
	}
}
